package com.itheima.tanhua.admin.service;

import cn.hutool.core.collection.CollUtil;
import com.itheima.dubbo.api.ActivityApi;
import com.itheima.dubbo.api.SummaryApi;
import com.itheima.dubbo.api.UserApi;
import com.itheima.model.domain.*;
import com.itheima.model.enums.AgeRangeEnum;
import com.itheima.model.enums.AreaEnum;
import com.itheima.model.enums.GenderTypeEnum;
import com.itheima.model.enums.LogTypeEnum;
import com.itheima.model.vo.DashUsersVo;
import com.itheima.model.vo.SummaryVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DashboardService {
    @DubboReference(timeout = 100000000)
    private UserApi userApi;
    @DubboReference(timeout = 100000000)
    private ActivityApi activityApi;
    @DubboReference(timeout = 100000000)
    private SummaryApi summaryApi;
/*
* 概要统计信息
* */
    public SummaryVo querySummary() {

        //查询到昨天的summary记录
        String nowDate = new SimpleDateFormat("yyyyMMdd").format(new Date());//今天的日期
        Integer todayInteger = Integer.valueOf(nowDate);
        Integer yestodayInteger = todayInteger-1;
        String yestoday = yestodayInteger.toString();
        Summary summary =  summaryApi.queryByDate(yestoday);
        if (summary==null){
            summary.setCumulativeUsers(0);
            summary.setActivePassMonth(0);
            summary.setActivePassWeek(0);
            summary.setNewUsersToday(0);
            summary.setNewUsersTodayRate(0);
            summary.setLoginTimesToday(0);
            summary.setLoginTimesTodayRate(0);
            summary.setActiveUsersToday(0);
            summary.setActiveUsersTodayRate(0);
            summary.setUseTimePassWeek(0);
            summary.setActiveUsersYesterday(0);
            summary.setActiveUsersYesterdayRate(0);
        }
        //1.累计用户---查询用户总人数
        Integer cumulativeUsers = userApi.findAllCounts();

        //2.今日新增用户---今天的所有的注册用户的记录
        Summary  sumarry=  activityApi.queryActivityCounts(nowDate, LogTypeEnum.REGISTER.getValue());
       Integer newUsersToday =0;
        if (sumarry!=null){
            newUsersToday = sumarry.getNewUsersToday();
       }
        //3.过去七天活跃用户
        Integer activePassWeek =  userApi.finActivityForDays(7);

        //4.过去30天活跃的用户
        Integer activePassMonth = userApi.finActivityForDays(30);

//        5.private Integer newUsersTodayRate;//今日新增用户涨跌率单位百分数，正数为涨，负数为跌
        Integer newUsersTodayRate = newUsersToday-summary.getNewUsersToday();

        //6.登录次数
        //根据活动类型查出今天的活动记录(所有人的登录记录)
        List<Activity> logActivitys = activityApi.queryActivity(nowDate, LogTypeEnum.LOGIN.getValue());
        //取出记录中的活动执行次数
        List<Integer> logCountList;
        if (CollUtil.isEmpty(logActivitys)){
            logCountList = new ArrayList<>();
        }else {
            logCountList = CollUtil.getFieldValues(logActivitys, "activityCount", Integer.class);
        }
//        将次数相加得到登录总数
        Integer loginTimesToday = 0;
        if (CollUtil.isNotEmpty(logCountList)){
            for (Integer count : logCountList) {
                loginTimesToday =loginTimesToday+count;
            }
        }

//           7. private Integer loginTimesTodayRate;//今日登录次数涨跌率，单位百分数，正数为涨，负数为跌
        Integer loginTimesTodayRate = (loginTimesToday-summary.getLoginTimesToday())*100;

        // 8.今日活跃用户
//        查询今天的所有活动记录中包含的用户总数--去重
        Summary summary1 = activityApi.queryActiveUserCounts(nowDate);
        Integer activeUsersToday =0;
        if (summary1!=null){
            activeUsersToday = summary1.getActiveUsersToday();
        }

//        9.    private Integer activeUsersTodayRate;//今日活跃用户涨跌率，单位百分数，正数为涨，负数为跌
        Integer activeUsersTodayRate = (activeUsersToday-summary.getActiveUsersToday())*100;

//        10.    private Integer useTimePassWeek;//过去7天平均日使用时长，单位秒
        //七条带有每天的最早和最晚的数据的记录
        List<Activity> activitylist = activityApi.queryActivityByDesc(nowDate);
        long sum = 0L;
        for (Activity activity : activitylist) {
            //取出这条记录的时间
            SimpleDateFormat sdf = new SimpleDateFormat("HHssmm");

            long last = activity.getUpdated().getTime();
            long first = activity.getCreated().getTime();
            sum = sum+(last-first);
        }
        int useTimePassWeekAvg = (int) (sum/7)/60000;

        Integer useTimePassWeek = Integer.valueOf(useTimePassWeekAvg);

//        11.private Integer activeUsersYesterday;//昨日活跃用户
        Integer activeUsersYesterday = summary.getActiveUsersToday();

//        12. private Integer activeUsersYesterdayRate;//昨日活跃用户涨跌率，单位百分数，正数为涨，负数为跌
        Integer activeUsersYesterdayRate = (activeUsersYesterday-summary.getActiveUsersYesterday())*100;

        Summary newSummary = new Summary();
        newSummary.setCumulativeUsers(cumulativeUsers);
        newSummary.setActivePassMonth(activePassMonth);
        newSummary.setActivePassWeek(activePassWeek);
        newSummary.setNewUsersToday(newUsersToday);
        newSummary.setNewUsersTodayRate(newUsersTodayRate);
        newSummary.setLoginTimesToday(loginTimesToday);
        newSummary.setLoginTimesTodayRate(loginTimesTodayRate);
        newSummary.setActiveUsersToday(activeUsersToday);
        newSummary.setActiveUsersTodayRate(activeUsersTodayRate);
        newSummary.setUseTimePassWeek(useTimePassWeek);
        newSummary.setActiveUsersYesterday(activeUsersYesterday);
        newSummary.setActiveUsersYesterdayRate(activeUsersYesterdayRate);
        newSummary.setCreatedDate(nowDate);

        summaryApi.save(newSummary);
        SummaryVo summaryVo = new SummaryVo();
        BeanUtils.copyProperties(newSummary,summaryVo);
        return summaryVo;
    }
    /**
     * 新增、活跃用户、次日留存率
     * */
    public DashUsersVo queryUsersByType(Integer type, Long sd, Long ed) {
        //根据接收到的type判断操作
        Calendar calendar = Calendar.getInstance();
        Integer year = calendar.get(Calendar.YEAR);
        Integer lastYear = year-1;
        DashUsersVo dashUsersVo = new DashUsersVo();
        //如果接收到的是101,查找新增用户
        if (type==101){
            //1.按照指定的日期范围查找
            //2.查找今年每月的新增用户---按时间查找->用户活动类型为注册的活动记录个数
            List<DashUserForSql> dashUserForSqlYearList = activityApi.queryByDateRange(2020,LogTypeEnum.REGISTER.getValue());
            List<DashUser> dashUsersForYear = new ArrayList<>();
            if (CollUtil.isNotEmpty(dashUserForSqlYearList)){
                for (DashUserForSql dashUserForSql : dashUserForSqlYearList) {
                    if (dashUserForSql!=null){
                        DashUser dashUser = new DashUser();
                        dashUser.setTitle(""+dashUserForSql.getTitle()+"月");
                        dashUser.setAmount(dashUserForSql.getAmount());
                        dashUsersForYear.add(dashUser);
                    }
                }
                dashUsersVo.setThisYear(dashUsersForYear);
            }
//            3.查找去年每月的新增用户---按时间查找->用户活动类型为注册的活动记录个数
            List<DashUserForSql> dashUserForSqlLastList = activityApi.queryByDateRange(2019, LogTypeEnum.REGISTER.getValue());
            List<DashUser> dashUsersForLast = new ArrayList<>();
            if (CollUtil.isNotEmpty(dashUserForSqlLastList)){
                for (DashUserForSql dashUserForSql : dashUserForSqlLastList) {
                    if (dashUserForSql!=null){
                        DashUser dashUser = new DashUser();
                        dashUser.setTitle(""+dashUserForSql.getTitle()+"月");
                        dashUser.setAmount(dashUserForSql.getAmount());
                        dashUsersForLast.add(dashUser);
                    }
                }
                dashUsersVo.setLastYear(dashUsersForLast);
            }//如果接收到的是102,查找活跃用户
        }else if (type==102){
            //1.按照指定的日期范围查找
            //2.查找今年每月的新增用户---按时间查找->用户活动类型为注册的活动记录个数
            List<DashUserForSql> dashUserForSqlYearList = activityApi.queryByLastDateRange(2020);
            List<DashUser> dashUsersForYear = new ArrayList<>();
            if (CollUtil.isNotEmpty(dashUserForSqlYearList)){
                for (DashUserForSql dashUserForSql : dashUserForSqlYearList) {
                    if (dashUserForSql!=null){
                        DashUser dashUser = new DashUser();
                        dashUser.setTitle(""+dashUserForSql.getTitle()+"月");
                        dashUser.setAmount(dashUserForSql.getAmount());
                        dashUsersForYear.add(dashUser);
                    }
                }
                dashUsersVo.setThisYear(dashUsersForYear);
            }
//            3.查找去年每月的新增用户---按时间查找->用户活动类型为注册的活动记录个数
            List<DashUserForSql> dashUserForSqlLastList = activityApi.queryByLastDateRange(2019);
            List<DashUser> dashUsersForLast = new ArrayList<>();
            if (CollUtil.isNotEmpty(dashUserForSqlLastList)){
                for (DashUserForSql dashUserForSql : dashUserForSqlLastList) {
                    if (dashUserForSql!=null){
                        DashUser dashUser = new DashUser();
                        dashUser.setTitle(""+dashUserForSql.getTitle()+"月");
                        dashUser.setAmount(dashUserForSql.getAmount());
                        dashUsersForLast.add(dashUser);
                    }
                }
                dashUsersVo.setLastYear(dashUsersForLast);
            }//        如果接收到的是103.查找每月次日留存率
        }else if (type==103){
            List<DashUser> dashUsersForYear = new ArrayList<>();

            for (Integer i = 1; i <=12; i++) {
                DashUser dashUser = activityApi.queryActiveForMonth(2020,i);
                if (dashUser==null){
                    dashUser = new DashUser();
                    dashUser.setAmount(0);
                }
                dashUser.setTitle(""+i+"月");
                dashUsersForYear.add(dashUser);
            }
            dashUsersVo.setThisYear(dashUsersForYear);
            List<DashUser> dashUsersForLast = new ArrayList<>();
            for (Integer i = 1; i <=12; i++) {
                DashUser dashUser = activityApi.queryActiveForMonth(2019,i);
                if (dashUser==null){
                    dashUser = new DashUser();
                    dashUser.setAmount(0);
                }
                dashUser.setTitle(""+i+"月");
                dashUsersForLast.add(dashUser);
            }
            dashUsersVo.setLastYear(dashUsersForLast);
        }
        return dashUsersVo;
    }

    /**
     * 注册用户分布，行业top、年龄、性别、地区
     * */
    public Distribution distribution(Long sd, Long ed) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      /*  String startDate = sdf.format(new Date(sd))+" 00:00:00";
        String endDate = sdf.format(new Date(ed))+" 23:59:59";*/
        Distribution distribution = new Distribution();
        String startDate = "2019-08-02 00:00:00";
        String endDate = "2019-08-02 23:59:59";
//        1.查年龄分布区间
        List<String> ageRangeEnum = new ArrayList<>();
        Collections.addAll(ageRangeEnum,AgeRangeEnum.UNDER_TWENTY.getDesc(),
                AgeRangeEnum.TWENTY_FIRST.getDesc(),
                AgeRangeEnum.TWENTY_LAST.getDesc(),
                AgeRangeEnum.THIRTY.getDesc(),
                AgeRangeEnum.FORTY.getDesc(),
                AgeRangeEnum.OVER_FIFTY.getDesc()
                );
//      1.查年龄分布
        List<DashUser> dashUserListForAge =  activityApi.queryAgeRangeByDate(startDate,endDate);
        List<DashUser> AgeDistribution = checkData(ageRangeEnum, dashUserListForAge);
        distribution.setAgeDistribution(AgeDistribution);


//        2.查行业分布前十名
        //行业的分布区间
        List<String> workRangeEnum = new ArrayList<>();
        Collections.addAll(workRangeEnum,"物流","文娱","医疗","金融","餐饮","教育","住宿","地产","服务","制造");
        List<DashUser> dashUserListForWork =  activityApi.queryWorkRangeByDate(startDate,endDate);
//        List<DashUser> IndustryDistribution = checkData(workRangeEnum, dashUserListForWork);
        if (CollUtil.isEmpty(dashUserListForWork)){
            dashUserListForWork = new ArrayList<>();
            distribution.setIndustryDistribution(dashUserListForWork);
        }else{
            if (dashUserListForWork.size()<10){
                //提取集合中的title字段
                List<String> title = CollUtil.getFieldValues(dashUserListForWork, "title", String.class);
                //找出缺少哪个区间的数据
                List<String> workRangeLow = subList1(workRangeEnum,title);
                for (int i = dashUserListForWork.size(), j =0; i < 10; i++) {
                    DashUser dashUser = new DashUser();
                    dashUser.setTitle(workRangeLow.get(j++));
                    dashUser.setAmount(0);
                    dashUserListForWork.add(dashUser);
                }
                distribution.setIndustryDistribution(dashUserListForWork);
            }else {
                distribution.setIndustryDistribution(dashUserListForWork);
            }
        }
//            3.查性别分布
        List<DashUser> dashUserMapForSex =  activityApi.querySexRangeByDate(startDate,endDate);
        if (CollUtil.isEmpty(dashUserMapForSex)) {
            dashUserMapForSex= new ArrayList<>();
            distribution.setGenderDistribution(dashUserMapForSex);
        }else {
            for (DashUser userMapForSex : dashUserMapForSex) {
                if (userMapForSex.getTitle().equals(GenderTypeEnum.MAN.getValue())) {
                    userMapForSex.setTitle(GenderTypeEnum.MAN.getName());
                }else {
                    userMapForSex.setTitle(GenderTypeEnum.WOMAN.getName());
                }
            }
            distribution.setGenderDistribution(dashUserMapForSex);
        }

//        4.地区分布

//        5.地区合计
        List<DashUser> dashUserListForLocal =  activityApi.queryLocalRangeByDate(startDate,endDate);
        List<DashUser> localTotal = new ArrayList<>();
        localTotal.add(new DashUser("华中地区",0));
        localTotal.add(new DashUser("华北地区",0));
        localTotal.add(new DashUser("华东地区",0));
        localTotal.add(new DashUser("华南地区",0));
        localTotal.add(new DashUser("西北地区",0));
        localTotal.add(new DashUser("东北地区",0));
        localTotal.add(new DashUser("西南地区",0));

        if (CollUtil.isEmpty(dashUserListForLocal)) {
            dashUserListForLocal = new ArrayList<>();
            distribution.setLocalTotal(dashUserListForLocal);
        }else {
            //提取所有的title,获得地区信息
//            List<String> title = CollUtil.getFieldValues(dashUserListForLocal, "title", String.class);
//dashUserListForLocal--->title:河南省-鹤壁市;amount:232
//            遍历集合对所有的title 进行截取subString(0,2)然后存回去
            for (DashUser dashUser : dashUserListForLocal) {
                String title = dashUser.getTitle();
                String substring = title.substring(0, 2);
                if (substring.equals("内蒙")){
                    substring = "内蒙古";
                }else if (substring.equals("黑龙")){
                    substring = "黑龙江";
                }
                dashUser.setTitle(substring);
                String areaByProvince = AreaEnum.getAreaByProvince(substring);
                //            通过AreaEnum.getAreaByProvince(title)获取到地区area
//            然后遍历地区的集合,将amount+1
                for (DashUser user : localTotal) {
                    if (areaByProvince.equals(user.getTitle())){
                        user.setAmount(user.getAmount()+1);
                    }
                }
            }
            distribution.setLocalTotal(localTotal);

//            处理完之后所有的对象格式为title:安徽,amount:121
            List<DashUser> dashUserListForLocalTransfer = new ArrayList<>();
            dashUserListForLocal.parallelStream().collect(Collectors.groupingBy(o->(o.getTitle()),Collectors.toList())).forEach(
                    (id,transfer)->{
                        transfer.stream().reduce((a,b)->new DashUser(a.getTitle(),a.getAmount())).ifPresent(dashUserListForLocalTransfer::add);
                    }
            );
            distribution.setLocalDistribution(dashUserListForLocalTransfer);
        }

        return distribution;
    }
    /**
     * 差集(基于常规解法）优化解法1 适用于中等数据量
     * 求List1中有的但是List2中没有的元素
     */
    public List<String> subList1(List<String> list1, List<String> list2) {
        //空间换时间 降低时间复杂度
        Map<String, String> tempMap = new HashMap<>();
        for(String str:list2){
            tempMap.put(str,str);
        }
        //LinkedList 频繁添加删除 也可以ArrayList容量初始化为List1.size(),防止数据量过大时频繁扩容以及数组复制
        List<String> resList = new LinkedList<>();
        for(String str:list1){
            if(!tempMap.containsKey(str)){
                resList.add(str);
            }
        }
        return resList;
    }

    public List<DashUser> checkData(List<String> titleList,List<DashUser> dashUserList){
        if (CollUtil.isEmpty(dashUserList)){
            dashUserList = new ArrayList<>();
            return dashUserList;
        }else {
            //查出的数据为:
            /*18-23岁--14  24-30岁--27 31-40岁--27 41-50岁--31  -->4条数据,
            应该有6条数据,如果集合长度小于6,说明少了数据,循环判断少了哪条数据*/
            if (dashUserList.size()<titleList.size()){
                // 遍历里面的元素,如果title没有匹配的分区就赋值为0
                //提取集合中的title字段
                List<String> title = CollUtil.getFieldValues(dashUserList, "title", String.class);
                //找出缺少哪个区间的数据
                List<String> ageRangeLow = subList1(titleList,title);
                for (String s : ageRangeLow) {
                    DashUser dashUser = new DashUser();
                    dashUser.setTitle(s);
                    dashUser.setAmount(0);
                    dashUserList.add(dashUser);
                }
                return dashUserList;
            }else {
                return dashUserList;
            }

    }
}
}
